package solver.moves;

import java.util.Collections;
import java.util.List;
import java.util.Random;

import model.IncrementalCostCalculator;
import model.IncrementalValidator;
import model.SolverEnvironment;
import model.Problem;
import model.Solution;

import command.IncrementalMoveProcessToMachineCommand;
import command.Invoker;

public class RandomMachinePairBestProcessExchangeMove extends AbstractMove {

	static int max_combinations=20;
	public RandomMachinePairBestProcessExchangeMove(SolverEnvironment env) {
		super(env);
	}

	int orig_m1_index,orig_m2_index;

	@Override
	public boolean performMove() {
		int bestM1Process = -1 , bestM2Process = -1;
		long bestCost = Long.MAX_VALUE;
		Solution pot_sol = env.getPotentialSolution();

		selectMachinePair();	
		List<Integer> l1 = getCurrent_solution().getProcessesForMachine(orig_m1_index);
		List<Integer> l2 = getCurrent_solution().getProcessesForMachine(orig_m2_index);
		if (l1.size()==0 || l2.size()==0)
			return false;
		Collections.shuffle(l1,env.getRandom());
		Collections.shuffle(l2,env.getRandom());
		int m1C=0;
		for(Integer movePid1:l1){
			int m2C=0;
			for(Integer movePid2:l2){
				if (getIv().isProcessExchangeFeasibleNoSchedule(movePid1, orig_m1_index, movePid2, orig_m2_index)){
					long localCost=env.getCostCalculator().getNewSolutionCost()+
							env.getCostCalculator().getProcessExcahngeProfit(pot_sol, movePid1, movePid2,orig_m1_index,orig_m2_index);
					if(localCost<bestCost){
						bestCost = localCost;
						bestM1Process = movePid1;
						bestM2Process = movePid2;
					}
				}
				if(m2C++>max_combinations) break;
			}
			if(m1C++>max_combinations) break;
		}
		
		if(bestM1Process !=-1){
			env.getCostCalculator().getProcessExcahngeProfit(pot_sol, bestM1Process, bestM2Process,orig_m1_index,orig_m2_index);
			makeExchange(bestM1Process,orig_m1_index, bestM2Process, orig_m2_index);
			getCc().updateNewSolutionCost();
			return true;
		}
		else
			return false;
	}
	
	protected void selectMachinePair(){
		orig_m1_index = getRandom().nextInt(getProblem().M);
		orig_m2_index = getRandom().nextInt(getProblem().M);
		
		while(orig_m1_index==orig_m2_index)
			orig_m1_index = getRandom().nextInt(getProblem().M);
	}

}
